package org.lc.cmd.model;

import java.util.ArrayList;
import java.util.List;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.AttributedStyle;

@EqualsAndHashCode
public class StyledString implements CharSequence {
    private final List<StyledItem> items = new ArrayList<>();

    public StyledString(String data) {
        items.add(new StyledItem(data));
    }

    public StyledString(String data, int rgb) {
        items.add(new StyledItem(data, rgb));
    }

    public StyledString(StyledString string) {
        items.addAll(string.items);
    }

    @Override
    public int length() {
        return items.stream().mapToInt(StyledItem::length).sum();
    }

    @Override
    public char charAt(int index) {
        int currentIndex = 0;
        for (StyledItem item : items) {
            if (index < currentIndex + item.length()) {
                return item.charAt(index - currentIndex);
            }
            currentIndex += item.length();
        }
        throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length());
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        if (start < 0 || end > length() || start > end) {
            throw new IndexOutOfBoundsException("Start: " + start + ", End: " + end + ", Length: " + length());
        }

        StringBuilder sb = new StringBuilder();
        int currentIndex = 0;
        for (StyledItem item : items) {
            if (end <= currentIndex) {
                break;
            }

            int itemStart = Math.max(start - currentIndex, 0);
            int itemEnd = Math.min(end - currentIndex, item.length());

            if (itemStart < itemEnd) {
                sb.append(item.subSequence(itemStart, itemEnd));
            }
            currentIndex += item.length();
        }

        return sb.toString();
    }

    public void append(String data) {
        items.add(new StyledItem(data));
    }

    public void append(StyledString string) {
        items.addAll(string.items);
    }

    public AttributedString toJlineString() {
        AttributedStringBuilder builder = new AttributedStringBuilder();
        for (StyledItem item : items) {
            builder.append(item.toJlineString());
        }
        return builder.toAttributedString();
    }

    @AllArgsConstructor
    private static class StyledItem implements CharSequence {
        private String data;
        private int rgb = 0;

        public StyledItem(String data) {
            this.data = data;
        }

        @Override
        public int length() {
            return data.length();
        }

        @Override
        public char charAt(int index) {
            return data.charAt(index);
        }

        @Override
        public CharSequence subSequence(int start, int end) {
            return data.subSequence(start, end);
        }

        @Override
        public String toString() {
            return data;
        }

        public AttributedString toJlineString() {
            if (rgb == 0) {
                return new AttributedString(data);
            }
            return new AttributedString(data, AttributedStyle.DEFAULT.foregroundRgb(rgb));
        }
    }
}
